
-- can't resolve seggfault on luasec, luasocket'
-- local https = "wget"
local json = require("cjson")

-- for testing 
function printTable(t)
    for key, value in pairs(t) do
        print(key, value)
    end
end

function tokenizeString(inputString, delimiter)
    local tokens = {}
    for token in inputString:gmatch("[^" .. delimiter .. "]+") do
        table.insert(tokens, token)
    end
    return tokens
end

function get(link)
    local args = {
        "-qO-",
        link
    }
    local data = pandoc.pipe("wget", args, "")
    local parsed = json.decode(data)
--     print(link)
    return parsed
end

function get_epoch_time(timestamp)
    local pattern = "(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).000Z"
    local year, month, day, hour, min, sec = timestamp:match(pattern)
    local epoch = os.time({
        year = year,
        month = month,
        day = day,
        hour = hour,
        min = min,
        sec = sec
    })
    return epoch
end

function get_short_date(timestamp)
    return os.date(
        "%a, %B %d, %Y", get_epoch_time(timestamp)
    )
end

function write_comments(pleroma_posts, instance, show_avatars)
    show_avatars = show_avatars or false

    function get_user(acct_data, instance, include_img)
        -- user data
        local user_info = ""
        local result = ""
        local vars = {
            alias = acct_data["display_name"],
            uid = acct_data["id"],
            handle = acct_data["acct"],
            host=instance
        }
        if include_img then 
            user_info = [[
            <figure>
                <img src="$avatar$" loading="lazy" alt="avatar"/>
                <figcaption>$alias$ <a href="$host$/users/$uid$">@$handle$</a> </figcaption>
            </figure>
            ]]
            vars.avatar = acct_data["avatar_static"]
            result = user_info:gsub("%$(%w+)%$", vars)
        else
            user_info = "<p>$alias$ <a href=\"$host$/users/$uid$\">@$handle$</a></p>"
            result = user_info:gsub("%$(%w+)%$", vars)
        end
        return result
    end

    function get_card(card, instance)
        if card == nil or type(card) ~= "table" then
            return ""
        end
        if card["provider_url"] == instance then
            -- skip rendering a card
            return ""
        end
--         print(type(card))
        local card_template = [[
    <article class="card">
        <header>
            <h1 class="card-title">$title$</h1>
            <p class="card-description">$description$</p>
        </header>
<!--        <img src="$image$" alt="$image_description$" class="card-image" loading="lazy"/> -->
        <footer>
            <a href="$link$" class="card-link">Read More</a>
        </footer>
    </article>
        ]]
        local vars = {
            title = card["title"],
            description = card["description"],
            image = card["image"],
            image_description=card["image_description"],
            link = card["url"]
        }
        return card_template:gsub("%$(%w+)%$", vars)
    end

    function get_media(attachments)
        if type(attachments) ~= "table" then
            return ""
        end
        if #attachments < 1 then
            return ""
        end
        local media_list = {"<p>media attached: </p><ol>"}
        local item = "<li><a href=\"$link$\">$mime$</a></li>"
        for _, v in pairs(attachments) do
            local vars = {
                link = v["preview_url"],
                mime = v["pleroma"]["mime_type"]
            }
            local foo = item:gsub("%$(%w+)%$", vars)
            print(foo)
            table.insert(media_list, foo)
        end
        table.insert(media_list, "</ol>")
        return table.concat(media_list, "\n")
    end

    function get_poll(poll)
        if type(poll) ~= "table" then
            return ""
        end
        local bar_chart = {"<div class=\"chart\">"}
        local bar_template = [[
            <div class="bar-container">
                <div class="bar" style="width: $pct$%;">
                    <span>$pct$%</span>
                </div>
                <div class="bar-text">
                    $label$
                </div>
            </div>
        ]]
        local total_votes = math.floor(poll["votes_count"])
        local total_voters = math.floor(poll["voters_count"])
        for _, v in pairs(poll["options"]) do
            local percentage = (v["votes_count"]/total_votes) * 100
            local rounded = math.floor(0.5 + percentage)
            local vars = {
                label = v["title"],
                pct = rounded
            }
            local bar = bar_template:gsub("%$(%w+)%$", vars)
            table.insert(bar_chart, bar)
        end
        -- close chart div
        table.insert(bar_chart, "</div>")

        local summary = "<p>$x$ people have cast $y$ votes</p>"
        local foo = summary:gsub(
            "%$(%w+)%$", 
            {x=total_voters, y=total_votes}
        ) 
        table.insert(bar_chart, foo)
        return table.concat(bar_chart,"\n")
    end

    if #pleroma_posts == 0  then
        return ""
    end
    local template = [[
<article class="pleroma-comment" id="pleroma-comment$i$">
    <h3>
        #$i$ <a href="$host$/notice/$pid$">$datetime$</a>
    </h3>
    $user$
    <blockquote>
        $text$
    </blockquote>
    $card$
    $attributes$
</article>
]]
    local comments = {}
    local replies = pleroma_posts-- ["descendants"]
    for i, post in ipairs(replies) do
        local pid = post["id"]
        local datetime = get_short_date(post["created_at"])
        local text = post["content"]

        local attrs = {}
        table.insert(
            attrs, get_media(post["media_attachments"])
        )
        table.insert(attrs, get_poll(post["poll"]))

        local interpolated = template:gsub("%$(%w+)%$", {
            i= #replies - i + 1,
            host=instance,
            pid=pid,
            datetime=datetime,
            user=get_user(post["account"], instance, true),
            text = text,
            card = get_card(post["card"], instance),
            attributes = table.concat(attrs)
        })
--         print(interpolated)
        table.insert(
            comments, pandoc.RawBlock("html", interpolated)
        )
    end
--     print(comments)
    return comments
end

function combine_tables(a,b)
    -- iterate through b, add to a
    for i=1,#b do
        table.insert(a, b[i])
    end
    return a
end

function get_url_from_pandoc_str(pandoc_str) 
    local str = pandoc.utils.stringify(pandoc_str)
    -- 1 = protocol, 2 = host ...
    -- https://host.tld/notice/12345
    local tokens = tokenizeString(str, '/')
    local id = tokens[#tokens]

    local host = tokens[2]
    local id   = tokens[#tokens]
    local link = str

    return link, host, id
end

function get_status(host, post_id)
    local url = "https://" .. host .. "/api/v1/statuses/" .. post_id
    print(url)
    return get(url)
end

function get_replies(host, id)
    local url = "https://" .. host ..  "/api/v1/statuses/" .. id .. "/context"
    print(url)
    local got = get(url)
    return got["descendants"]
end

function Meta(meta)
    local pleroma_urls = meta["pleroma-urls"]
--     print(elem)
    if pleroma_urls == nil then
        return -- abort
    end
    local all_replies = {}
    local hrefs = {}
    local host = ""
    -- for each listed url in "pleroma-urls"
    for _, v in pairs(pleroma_urls) do
        local link, domain, id = get_url_from_pandoc_str(v)
        host = domain
        table.insert(hrefs, 
            {link = link, id = id}
        )
        local op = get_status(host, id)
        table.insert(all_replies, op)
        local replies = get_replies(host, id)
        combine_tables(all_replies, replies)
    end
    table.sort(all_replies, 
        function(a, b) 
            local ta = get_epoch_time(a["created_at"])
            local tb = get_epoch_time(b["created_at"])
            return ta > tb
        end
    )
    local c = write_comments(all_replies, "https://" .. host)
    meta["pleroma-comments"] = c
    meta["pleroma-comments-count"] = #c
    meta["pleroma-has-comments"] = (#c > 0)
    meta["pleroma"] = hrefs
    return meta
end


